# -*- coding: utf-8 -*-
import agraph

from clang.cindex import TranslationUnit
import clang.cindex as ci
import igraph
from common import walk_ast_tree
from utils.unused import FunctionSignature
from common import logable, trace_method
from common import NDW_DEBUG

__author__ = 'totem3006'


@logable
class FunctionCallDepend(object):
    def __init__(self, max_depth=100):
        import igraph
        self.__max_depth = max_depth
        self.__func = None
        self.graph = igraph.Graph(directed=True)

    @trace_method
    def load_from_tu(self, tu):

        def func_call_visitor_callback(node, parent, **kwargs):
            if node.kind == ci.CursorKind.CALL_EXPR:
                call_from = kwargs["call_from"]
                graph = kwargs["graph"]
                defen = node.get_definition()

                if defen is None:
                    # this is library function
                    rn = node.referenced
                    label = "%(type)s %(sign)s" % {"type": rn.result_type.spelling, "sign": rn.displayname}
                    graph.add_vertex(node.displayname, label=label)

                    start = node.displayname
                else:
                    start = node.get_definition().spelling

                fin = call_from.spelling

                if not graph.are_connected(fin, start):
                    graph.add_edge(fin, start)
            return 0

        def func_decl_visitor_callback(node, parent, **kwargs):
            if node.kind == ci.CursorKind.FUNCTION_DECL:
                if node.location.file.name.startswith("/usr"):
                    # this is func def from stdlib;
                    return 1

                graph = kwargs["graph"]
                node_id = node.spelling
                func_name = node.spelling
                ctype = node.result_type.spelling
                sign = FunctionSignature(func_name, ctype, node.displayname)
                graph.add_vertex(node_id, label=str(sign), func_name=func_name,
                                 type=ctype, signature=sign)

                args = {"call_from": node, "graph": graph}

                walk_ast_tree(node, node, func_call_visitor_callback, **args)

                return 1

            return 0

        walk_ast_tree(tu.cursor, tu.cursor, func_decl_visitor_callback, graph=self.graph)

    @trace_method
    def render_image(self, output_file_name=None):
        layout = self.graph.layout("fr")
        args = {"layout": layout,
                "margin": 100,
                "vertex_label_angle": 5,
                "vertex_label_dist": 1,
                "vertex_shape": "circle"}
        igraph.plot(self.graph, output_file_name, **args)
